core/iter/sources/successors.rs
1use crate::fmt;
2use crate::iter::FusedIterator;
3
4/// Creates an iterator which, starting from an initial item,
5/// computes each successive item from the preceding one.
6///
7/// This iterator stores an optional item (`Option<T>`) and a successor closure (`impl FnMut(&T) -> Option<T>`).
8/// Its `next` method returns the stored optional item and
9/// if it is `Some(val)` calls the stored closure on `&val` to compute and store its successor.
10/// The iterator will apply the closure successively to the stored option's value until the option is `None`.
11/// This also means that once the stored option is `None` it will remain `None`,
12/// as the closure will not be called again, so the created iterator is a [`FusedIterator`].
13/// The iterator's items will be the initial item and all of its successors as calculated by the successor closure.
14///
15/// ```
16/// use std::iter::successors;
17///
18/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
19/// assert_eq!(powers_of_10.collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
20/// ```
21#[stable(feature = "iter_successors", since = "1.34.0")]
22#[rustc_diagnostic_item = "iter_successors"]
23pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
24where
25 F: FnMut(&T) -> Option<T>,
26{
27 // If this function returned `impl Iterator<Item=T>`
28 // it could be based on `from_fn` and not need a dedicated type.
29 // However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
30 Successors { next: first, succ }
31}
32
33/// An iterator which, starting from an initial item,
34/// computes each successive item from the preceding one.
35///
36/// This `struct` is created by the [`iter::successors()`] function.
37/// See its documentation for more.
38///
39/// [`iter::successors()`]: successors
40#[derive(Clone)]
41#[stable(feature = "iter_successors", since = "1.34.0")]
42pub struct Successors<T, F> {
43 next: Option<T>,
44 succ: F,
45}
46
47#[stable(feature = "iter_successors", since = "1.34.0")]
48impl<T, F> Iterator for Successors<T, F>
49where
50 F: FnMut(&T) -> Option<T>,
51{
52 type Item = T;
53
54 #[inline]
55 fn next(&mut self) -> Option<Self::Item> {
56 let item = self.next.take()?;
57 self.next = (self.succ)(&item);
58 Some(item)
59 }
60
61 #[inline]
62 fn size_hint(&self) -> (usize, Option<usize>) {
63 if self.next.is_some() { (1, None) } else { (0, Some(0)) }
64 }
65}
66
67#[stable(feature = "iter_successors", since = "1.34.0")]
68impl<T, F> FusedIterator for Successors<T, F> where F: FnMut(&T) -> Option<T> {}
69
70#[stable(feature = "iter_successors", since = "1.34.0")]
71impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 f.debug_struct("Successors").field("next", &self.next).finish()
74 }
75}